package lysjmaster.base.auth.service;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import lysjmaster.base.auth.domain.Permission;
import lysjmaster.base.auth.domain.Role;
import lysjmaster.base.auth.domain.RolePermission;
import lysjmaster.base.auth.domain.User;
import lysjmaster.base.auth.repository.PermissionRepository;
import lysjmaster.base.auth.repository.RolePermissionRepository;
import lysjmaster.base.auth.repository.RoleRepository;
import lysjmaster.base.auth.repository.UserRepository;
import lysjmaster.base.common.annotation.SystemLog;
import lysjmaster.base.common.exception.BaseException;
import lysjmaster.base.common.spring.base.BaseEntity;
import lysjmaster.base.common.spring.base.BaseRepository;
import lysjmaster.base.common.spring.base.BaseService;
import lysjmaster.base.common.spring.jpa.ConditionUtil;
import lysjmaster.base.common.spring.pagination.PageRequestDTO;
import lysjmaster.base.common.web.ParamUtil;
import lysjmaster.base.common.web.Resp;
import lysjmaster.base.common.web.RespUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Created by zk on 2019-12-05 2:23
 * @description
 */
@Slf4j
@Service
@Transactional
public class RoleService implements BaseService<Role> {
    @Resource
    private RoleRepository roleRepository;
    @Resource
    private UserRepository userRepository;
    @Resource
    private RolePermissionRepository rolePermissionRepository;
    @Resource
    private PermissionRepository permissionRepository;
    @Resource
    private AdminAuthentication adminAuthentication;


    @Override
    public BaseRepository<Role> getRepository() {
        return roleRepository;
    }

    /**
     * @author zk
     * @date 2019/12/6 11:23
     * @Description 分配角色权限
     */
    @Transactional
    public void editRolePerm(String id, String[] permissionIds) {
        Role role = findOne(id);
        if (role == null) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, "查无此角色");
        }
        //根据角色Id删除所有权限关系
        rolePermissionRepository.deleteByRoleId(id);
        List<RolePermission> saveData = new ArrayList<>(permissionIds.length);
        //根据Id列表获取所有权限，并构造ID-权限Map
        Map<String, Permission> permissionMap = permissionRepository.findAll(Arrays.asList(permissionIds))
                .parallelStream()
                .collect(Collectors.toMap(BaseEntity::getId, p -> p));
        for (String permissionId : permissionIds) {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(id);
            Permission permission = permissionMap.get(permissionId);
            if (permission == null) {
                throw new BaseException(Resp.ResStatus.PARAM_ERROR, "参数有误，请重新操作");
            }
            rolePermission.setPermissionId(permissionId);
            saveData.add(rolePermission);
        }
        rolePermissionRepository.save(saveData);
        //更新权限缓存
        adminAuthentication.init();
    }

    @Transactional
    public void deleteRole(String[] ids) {
        List<Role> roles = findAll(ids);
        List<User> userList = userRepository.findByRoleIdIn(Arrays.asList(ids));
        if (!ParamUtil.isBlank(userList)) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, StrUtil.format("该角色仍有用户在使用，请先全部更改"));
        }
        for (Role role : roles) {
            delete(role);
            rolePermissionRepository.deleteByRoleId(role.getId());
        }
        adminAuthentication.init();
    }

    public Page<Role> roleList(PageRequestDTO condition) {
        Page<Role> roles = list(condition);
        Set<String> roleIds = roles.getContent().parallelStream().map(BaseEntity::getId).collect(Collectors.toSet());
        List<RolePermission> rolePermissions = rolePermissionRepository.findByRoleIdIn(roleIds);
        //角色Id-权限Id列表
        HashMap<String, Set<String>> map = rolePermissions.parallelStream()
                .collect(Collectors.groupingBy(RolePermission::getRoleId, HashMap::new,
                        Collectors.mapping(RolePermission::getPermissionId, Collectors.toSet())));
        for (Role role : roles) {
            Set<String> pIds = map.get(role.getId());
            if (ParamUtil.isBlank(pIds)) {
                role.setPermissionIds(new HashSet<>());
            } else {
                role.setPermissionIds(pIds);
            }
        }
        return roles;


    }

}
